package com.newland.starpos.partner.service.remote;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.newland.starpos.partner.bean.po.User;
import com.newland.starpos.partner.bean.vo.RemainTimeVO;
import com.newland.starpos.partner.exception.CustomException;
import com.newland.starpos.partner.http.ResponseEnum;
import com.newland.starpos.partner.service.UserService;
import com.newland.starpos.partner.service.function.RedisCache;
import com.newland.starpos.partner.utils.HttpUtils;
import com.newland.starpos.partner.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class PortalService {

    public static final int MAX_ERROR_TIMES = 5;

    @Value(value = "${portal.domain}")
    private String portalDomain;

    @Autowired
    private RedisCache redisCache;

    // 注册
    public void createUser(String phoneNumber, Integer orgId) throws CustomException {
        String requestUrl = portalDomain + "/ws/v1/partner/register";
        // 组装请求体
        JSONObject content = new JSONObject();
        content.put("mobile", phoneNumber);
        content.put("belongsOrgan", String.valueOf(orgId));
        content.put("areaCode", "86");
        callRemotePortalService(requestUrl, content.toJSONString(), ResponseEnum.REGIST_PORTAL_ERROR);
    }

    // 登录
    public void login(String phoneNumber, String password, HttpServletRequest request) throws CustomException {
        String key = "PT_50005_" + phoneNumber;

        // 首先判断 失败次数是大于等于5
        String errorCount = redisCache.getString(key);
        if (StringUtils.isNotBlank(errorCount) && Integer.parseInt(errorCount) >= MAX_ERROR_TIMES) {
            throw new CustomException(ResponseEnum.LOGIN_ERROR_TIMES_GT);
        }
        String requestUrl = portalDomain + "/ws/v1/partner/login";
        // 组装请求体
        JSONObject content = new JSONObject();
        content.put("loginName", UserService.tranPhoneNumber2UserName(phoneNumber));
        content.put("loginPassword", password);
        content.put("opSys", getDeviceType(request));

        try {
            callRemotePortalService(requestUrl, content.toJSONString(), ResponseEnum.LOGIN_PORTAL_ERROR);
            redisCache.delete(key);
        } catch (CustomException e) {
            // 这里捕捉异常,如果是异常码为'50005',做对应处理,其他直接throw
            if (50005 != e.getCode())
                throw e;
            Long count = MAX_ERROR_TIMES - redisCache.increment(key, 1);
            redisCache.expire(key, 30, TimeUnit.MINUTES);
            throw new CustomException(ResponseEnum.LOGIN_ERROR_USERNAME_OR_PASSWORD, new RemainTimeVO(count));
        }
    }

    // 重置密码
    public void resetPassword(User existUser, String newPassword, HttpServletRequest request) throws CustomException {
        String requestUrl = portalDomain + "/ws/v1/partner/resetPass";
        // 组装请求体
        JSONObject content = new JSONObject();
        content.put("loginName", UserService.tranPhoneNumber2UserName(existUser.getTelephone()));
        content.put("newpassword", newPassword);
        content.put("opSys", getDeviceType(request));

        callRemotePortalService(requestUrl, content.toJSONString(), ResponseEnum.RESET_PORTL_ERROR);
        redisCache.delete("PT_50005_" + existUser.getTelephone());
    }

    // 修改密码
    public void modifyPassword(String telephone, String logPassword, String newPassword,
                               HttpServletRequest request) throws CustomException {

        String requestUrl = portalDomain + "/ws/v1/partner/modifyPass";
        // 组装请求体
        JSONObject content = new JSONObject();
        content.put("loginName", UserService.tranPhoneNumber2UserName(telephone));
        content.put("loginPassword", newPassword);
        content.put("newpassword", newPassword);
        content.put("opSys", getDeviceType(request));

        callRemotePortalService(requestUrl, content.toJSONString(), ResponseEnum.RESET_PORTL_ERROR);
        redisCache.delete("PT_50005_" + telephone);
    }


    private void callRemotePortalService(String portalUrl, String content, ResponseEnum responseEnum) throws CustomException {
        String response;
        try {
            response = HttpUtils.postJsonU8(portalUrl, content);
        } catch (Exception e) {
            log.error("调用portal失败,message:[{}]", e.getMessage());
            throw new CustomException(responseEnum);
        }
        JSONObject result = JSON.parseObject(response);
        String errorCode = result.getString("errorCode");
        if (!StringUtils.equals(errorCode, "0000")) {
            try {
                // portal返回码定义'1_9004'为用户名或者密码错误,这里转换为本系统 对应的返回码用以下一步对密码错误次数的登录限制
                if (StringUtils.equals(errorCode, "1_9004")) {
                    throw new CustomException(ResponseEnum.LOGIN_ERROR_USERNAME_OR_PASSWORD.code(), URLDecoder.decode(result.getString("message"), "UTF8"));
                }else if(StringUtils.equals(errorCode, "1_9005")){
                    throw new CustomException(ResponseEnum.UPDATE_PASSWORD_FAIL);
                }

                throw new CustomException(responseEnum.code(), URLDecoder.decode(result.getString("message"), "UTF8"));
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException("转码异常");
            }
        }
    }

    /**
     * 根据请求中的[user-agent]判断客户端设备类型
     * @param request
     * @return type(0 : android, 1 : ios)
     */
    public String getDeviceType(HttpServletRequest request) {
        String agent = request.getHeader("user-agent");
        if (StringUtils.isBlank(agent)) {
            return "0";
        }
        if (agent.contains("CFNetwork") || agent.contains("iPhone") || agent.contains("Darwin")) {
            return "1";
        }
        return "0";
    }
}
